home *** CD-ROM | disk | FTP | other *** search
/ Programming Sound Cards / Programming Sound Cards.iso / sound_08 / ctv-mod.asm < prev    next >
Assembly Source File  |  1995-01-01  |  27KB  |  1,385 lines

  1.        PAGE   ,132
  2.        TITLE  Sound Blaster Object Module
  3.        SUBTTL Main Program
  4.  
  5.  
  6. if1
  7.     ifdef small
  8.          %OUT   Small Model
  9.     else
  10.          %OUT   Large Model
  11.     endif
  12. endif
  13.  
  14.  
  15.  
  16. ifdef    small
  17.     _TEXT  SEGMENT  WORD PUBLIC 'CODE'
  18.     _TEXT  ENDS
  19. else
  20.     CTV_TEXT  SEGMENT  WORD PUBLIC 'CODE'
  21.     CTV_TEXT  ENDS
  22. endif
  23.  
  24.  
  25. _DATA  SEGMENT  WORD PUBLIC 'DATA'
  26. _DATA  ENDS
  27. CONST  SEGMENT  WORD PUBLIC 'CONST'
  28. CONST  ENDS
  29. _BSS   SEGMENT  WORD PUBLIC 'BSS'
  30. _BSS   ENDS
  31.  
  32.  
  33. DGROUP GROUP   CONST, _BSS, _DATA
  34.  
  35. ifdef  small
  36.        ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP
  37. else
  38.        ASSUME  CS: CTV_TEXT, DS: DGROUP, SS: DGROUP
  39. endif
  40.  
  41.  
  42.        PUBLIC      _io_addx, _intr_num, _voice_status
  43.        PUBLIC      _ctv_detect, _ctv_speaker, _ctv_output,
  44.        PUBLIC      _ctv_halt
  45.        PUBLIC      _ctv_pause, _ctv_continue, _ctv_uninstall
  46.        PUBLIC      _ctv_card_here
  47.  
  48.  
  49.  
  50.  
  51. _DATA  SEGMENT  WORD PUBLIC 'DATA'
  52.  
  53. ifdef  small
  54.        ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP
  55. else
  56.        ASSUME  CS: CTV_TEXT, DS: DGROUP, SS: DGROUP
  57. endif
  58.  
  59. _io_addx       DW   220H
  60. _intr_num      DB   0
  61. _voice_status  DW   0
  62.  
  63. ORG_INT_ADDX       LABEL     DWORD
  64. ORG_INT2_ADDX      LABEL     DWORD
  65.   ORG_INT2_OFF      DW       ?
  66.   ORG_INT2_SEG      DW       ?
  67. ORG_INT3_ADDX      LABEL     DWORD
  68.   ORG_INT3_OFF      DW       ?
  69.   ORG_INT3_SEG      DW       ?
  70. ORG_INT5_ADDX      LABEL     DWORD
  71.   ORG_INT5_OFF      DW       ?
  72.   ORG_INT5_SEG      DW       ?
  73. ORG_INT7_ADDX      LABEL     DWORD
  74.   ORG_INT7_OFF      DW       ?
  75.   ORG_INT7_SEG      DW       ?
  76.  
  77.  
  78. ;---------------------
  79. ;      DMA DATA      |
  80. ;---------------------
  81. DMA_CURRENT_PAGE    DB       ?
  82. DMA_CURRENT_ADDX    DW       ?
  83. DMA_CURRENT_COUNT   DW       ?
  84. PAGE_TO_DMA         DB       ?
  85. LEN_L_TO_DMA        DW       ?
  86. LEN_H_TO_DMA        DW       ?
  87. LAST_DMA_OFFSET     DW       ?
  88.  
  89.  
  90. _DATA  ENDS
  91.  
  92.  
  93. ifdef  small
  94.     _TEXT  SEGMENT     WORD PUBLIC 'CODE'
  95. else
  96.     CTV_TEXT  SEGMENT     WORD PUBLIC 'CODE'
  97. endif
  98.  
  99.        SUBTTL    DSP module
  100.  
  101. WAIT_TIME        EQU    0200H
  102. DMA_VOICE_IN     EQU    45H
  103. DMA_VOICE_OUT    EQU    49H
  104.  
  105. DSP_ID_CMD              EQU    0E0H
  106. DSP_VER_CMD             EQU    0E1H
  107. DSP_VI8_CMD             EQU    24H
  108. DSP_VO8_CMD             EQU    14H
  109. DSP_VO2_CMD             EQU    17H
  110. DSP_VO4_CMD             EQU    75H
  111. DSP_VO25_CMD            EQU    77H
  112. DSP_MDAC1_CMD           EQU    61H
  113. DSP_MDAC2_CMD           EQU    62H
  114. DSP_MDAC3_CMD           EQU    63H
  115. DSP_MDAC4_CMD           EQU    64H
  116. DSP_MDAC5_CMD           EQU    65H
  117. DSP_MDAC6_CMD           EQU    66H
  118. DSP_MDAC7_CMD           EQU    67H
  119. DSP_TIME_CMD            EQU    40H
  120. DSP_SILENCE_CMD         EQU    80H
  121. DSP_PAUSE_DMA_CMD       EQU    0D0H
  122. DSP_ONSPK_CMD           EQU    0D1H
  123. DSP_OFFSPK_CMD          EQU    0D3H
  124. DSP_CONT_DMA_CMD        EQU    0D4H
  125. DSP_INTRQ_CMD           EQU    0F2H
  126.  
  127. CMS_TEST_CODE            EQU         0C6H
  128. RESET_TEST_CODE          EQU         0AAH
  129.  
  130. CMS_EXIST                EQU         1
  131. FM_MUSIC_EXIST           EQU         2
  132. CTV_VOICE_EXIST          EQU         4
  133.  
  134. FM_WAIT_TIME             EQU         40H
  135.  
  136.  
  137. WRITE_DSP_TIME   PROC
  138.  
  139.        PUSH   CX
  140.  
  141.        MOV    CX,WAIT_TIME
  142.        MOV    AH,AL
  143.  
  144. WDT10:
  145.        IN     AL,DX
  146.        OR     AL,AL
  147.        JNS    WDT20
  148.  
  149.        LOOP   WDT10
  150.  
  151.        STC
  152.        JMP    SHORT WDT90
  153.  
  154. WDT20:
  155.        MOV    AL,AH
  156.        OUT    DX,AL
  157.        CLC
  158.  
  159. WDT90:
  160.        POP    CX
  161.        RET
  162.  
  163. WRITE_DSP_TIME   ENDP
  164.  
  165.  
  166.  
  167. READ_DSP_TIME    PROC
  168.  
  169.        PUSH   CX
  170.        PUSH   DX
  171.  
  172.        MOV    DX,_io_addx
  173.        ADD    DL,0EH
  174.  
  175.        MOV    CX,WAIT_TIME
  176.  
  177. RDT10:
  178.        IN     AL,DX
  179.        OR     AL,AL
  180.        JS     RDT20
  181.  
  182.        LOOP   RDT10
  183.        STC
  184.        JMP    SHORT RDT90
  185.  
  186. RDT20:
  187.        SUB    DL,4
  188.        IN     AL,DX
  189.        CLC
  190.  
  191. RDT90:
  192.        POP    DX
  193.        POP    CX
  194.        RET
  195.  
  196. READ_DSP_TIME    ENDP
  197.  
  198.  
  199. WRITE_DSP   PROC
  200.  
  201.        MOV    AH,AL
  202.        MOV    AL,0F0H
  203.  
  204. WD10:
  205.        IN     AL,DX
  206.        OR     AL,AL
  207.        JS     WD10
  208.  
  209.        MOV    AL,AH
  210.        OUT    DX,AL
  211.        RET
  212.  
  213. WRITE_DSP   ENDP
  214.  
  215.  
  216.  
  217. READ_DSP    PROC
  218.  
  219.        PUSH   DX
  220.  
  221.        MOV    DX,_io_addx
  222.        ADD    DL,0EH
  223.        SUB    AL,AL
  224.  
  225. RD10:
  226.        IN     AL,DX
  227.        OR     AL,AL
  228.        JNS    RD10
  229.  
  230.        SUB    DL,4
  231.        IN     AL,DX
  232.  
  233.        POP    DX
  234.        RET
  235.  
  236. READ_DSP    ENDP
  237.  
  238.  
  239. RESET_DSP     PROC
  240.  
  241.        MOV    DX,_io_addx
  242.        ADD    DL,6
  243.        MOV    AL,1
  244.        OUT    DX,AL
  245.  
  246.        IN     AL,DX
  247. RDSP05:
  248.        INC    AL
  249.        JNZ    RDSP05
  250.  
  251.        OUT    DX,AL
  252.  
  253.        MOV    CL,20H
  254.  
  255. RDSP10:
  256.        CALL   READ_DSP_TIME
  257.        CMP    AL,0AAH
  258.        JE     RDSP20
  259.  
  260.        DEC    CL
  261.        JNZ    RDSP10
  262.        MOV    AX,2
  263.        JMP    SHORT RDSP90
  264.  
  265. RDSP20:
  266.        SUB    AX,AX
  267.  
  268. RDSP90:
  269.        OR     AX,AX
  270.        RET
  271.  
  272. RESET_DSP     ENDP
  273.  
  274.  
  275. VERIFY_IO_CHK      PROC
  276.  
  277.        MOV    BX,2
  278.  
  279.        MOV    AL,DSP_ID_CMD
  280.        MOV    DX,_io_addx
  281.        ADD    DX,0CH
  282.        CALL   WRITE_DSP_TIME
  283.        JC     VIO90
  284.  
  285.        MOV    AL,0AAH
  286.        CALL   WRITE_DSP_TIME
  287.        JC     VIO90
  288.  
  289.        CALL   READ_DSP_TIME
  290.        JC     VIO90
  291.  
  292.        CMP    AL,055H
  293.        JNE    VIO90
  294.  
  295.        SUB    BX,BX
  296.  
  297. VIO90:
  298.        MOV    AX,BX
  299.        OR     AX,AX
  300.        RET
  301.  
  302. VERIFY_IO_CHK      ENDP
  303.  
  304.  
  305. VERIFY_INTR        PROC
  306.  
  307.        MOV    AL,2
  308.        MOV    DX,OFFSET DUMMY_DMA_INT2
  309.        MOV    BX,OFFSET DGROUP:ORG_INT2_ADDX
  310.        CALL   SETUP_INTERRUPT
  311.  
  312.        MOV    AL,3
  313.        MOV    DX,OFFSET DUMMY_DMA_INT3
  314.        MOV    BX,OFFSET DGROUP:ORG_INT3_ADDX
  315.        CALL   SETUP_INTERRUPT
  316.  
  317.        MOV    AL,5
  318.        MOV    DX,OFFSET DUMMY_DMA_INT5
  319.        MOV    BX,OFFSET DGROUP:ORG_INT5_ADDX
  320.        CALL   SETUP_INTERRUPT
  321.  
  322.        MOV    AL,7
  323.        MOV    DX,OFFSET DUMMY_DMA_INT7
  324.        MOV    BX,OFFSET DGROUP:ORG_INT7_ADDX
  325.        CALL   SETUP_INTERRUPT
  326.  
  327.        MOV    _intr_num,0
  328.  
  329.        MOV    DX,_io_addx
  330.        ADD    DX,0CH
  331.        MOV    AL,DSP_INTRQ_CMD
  332.        CALL   WRITE_DSP
  333.  
  334.  
  335.        IN     AL,21H
  336.  
  337.        PUSH   AX
  338.        AND    AL,01010011B
  339.        OUT    21H,AL
  340.  
  341.        SUB    AX,AX
  342.        MOV    CX,WAIT_TIME*4
  343.  
  344. VI10:
  345.        CMP    _intr_num,0
  346.        JNZ    VI90
  347.  
  348.        LOOP   VI10
  349.  
  350.        MOV    AX,3
  351.  
  352. VI90:
  353.        POP    BX
  354.  
  355.        PUSH   AX
  356.  
  357.        MOV    AL,BL
  358.        OUT    21H,AL
  359.  
  360.        MOV    AL,2
  361.        MOV    BX,OFFSET DGROUP:ORG_INT2_ADDX
  362.        CALL   RESTORE_INTERRUPT
  363.  
  364.        MOV    AL,3
  365.        MOV    BX,OFFSET DGROUP:ORG_INT3_ADDX
  366.        CALL   RESTORE_INTERRUPT
  367.  
  368.        MOV    AL,5
  369.        MOV    BX,OFFSET DGROUP:ORG_INT5_ADDX
  370.        CALL   RESTORE_INTERRUPT
  371.  
  372.        MOV    AL,7
  373.        MOV    BX,OFFSET DGROUP:ORG_INT7_ADDX
  374.        CALL   RESTORE_INTERRUPT
  375.  
  376.        POP    AX
  377.  
  378.        OR      AX,AX
  379.        RET
  380.  
  381. VERIFY_INTR        ENDP
  382.  
  383.  
  384. CHK_DSP_VERSION    PROC
  385.  
  386.        MOV    AL,DSP_VER_CMD
  387.        MOV    DX,_io_addx
  388.        ADD    DL,0CH
  389.        CALL   WRITE_DSP
  390.        CALL   READ_DSP
  391.        MOV    AH,AL
  392.        CALL   READ_DSP
  393.  
  394.        MOV    BX,1
  395.        CMP    AX,101H
  396.        JB     CDV90
  397.  
  398.        SUB    BX,BX
  399.  
  400. CDV90:
  401.        MOV    AX,BX
  402.        OR     AX,AX
  403.        RET
  404.  
  405. CHK_DSP_VERSION    ENDP
  406.  
  407.  
  408.  
  409. PAUSE_DSP_DMA     PROC
  410.  
  411.        PUSHF
  412.  
  413.        MOV    AH,DSP_PAUSE_DMA_CMD
  414.        MOV    BX,OFFSET DGROUP:_voice_status
  415.        SUB    CX,CX
  416.        MOV    DX,_io_addx
  417.        ADD    DL,0CH
  418.  
  419. PDD10:
  420.        STI                             ; enable intr. for voice-out intr
  421.        CMP    CX,[BX]                  ;   to update voice_status
  422.        JE     PDD90
  423.  
  424.        CLI                             ; disable intr. for following check
  425.        IN     AL,DX                    ;   which is timing critical
  426.        OR     AL,AL
  427.        JNS    PDD10                    ; wait for DSP not ready
  428.  
  429. PDD20:
  430.        IN     AL,DX
  431.        OR     AL,AL
  432.        JS     PDD20                    ; wait for DSP ready
  433.  
  434.        MOV    AL,AH
  435.        OUT    DX,AL                    ; write pause dma immediately
  436.  
  437. PDD90:
  438.        POPF
  439.        RET
  440.  
  441. PAUSE_DSP_DMA     ENDP
  442.  
  443.  
  444.        SUBTTL    DMA module
  445.  
  446.  
  447. ;--------------------------------------------
  448. ; entry: DH = dma mode                      :
  449. ;        DL = page                          :
  450. ;        AX = current addx                  :
  451. ;        CX = current count                 :
  452. ;--------------------------------------------
  453.  
  454.     DMA_ADDX_REG        EQU    02H
  455.     DMA_COUNT_REG       EQU    03H
  456.     DMA_MASK_REG        EQU    0AH
  457.     DMA_MODE_REG        EQU    0BH
  458.     DMA_FF_REG          EQU    0CH
  459.     DMA_PAGE_REG        EQU    83H
  460.  
  461.  
  462.  
  463. PROG_DMA      PROC
  464.  
  465.        PUSH   BX
  466.  
  467.        MOV    BX,AX
  468.  
  469.        MOV    AL,5
  470.        OUT    DMA_MASK_REG,AL
  471.  
  472.        SUB    AL,AL
  473.        OUT    DMA_FF_REG,AL
  474.  
  475.        MOV    AL,DH
  476.        OUT    DMA_MODE_REG,AL
  477.  
  478.        MOV    AL,BL
  479.        OUT    DMA_ADDX_REG,AL
  480.  
  481.        MOV    AL,BH
  482.        OUT    DMA_ADDX_REG,AL
  483.  
  484.        MOV    AL,CL
  485.        OUT    DMA_COUNT_REG,AL
  486.  
  487.        MOV    AL,CH
  488.        OUT    DMA_COUNT_REG,AL
  489.  
  490.        MOV    AL,DL
  491.        OUT    DMA_PAGE_REG,AL
  492.  
  493.        MOV    AL,1
  494.        OUT    DMA_MASK_REG,AL
  495.  
  496.        POP    BX
  497.        RET
  498.  
  499. PROG_DMA      ENDP
  500.  
  501.  
  502. CALC_20BIT_ADDX    PROC
  503.  
  504.        PUSH   CX
  505.  
  506.        MOV    CL,4
  507.        ROL    DX,CL
  508.        MOV    CX,DX
  509.        AND    DX,0FH
  510.        AND    CX,0FFF0H
  511.        ADD    AX,CX
  512.        ADC    DX,0
  513.  
  514.        POP    CX
  515.        RET
  516.  
  517. CALC_20BIT_ADDX    ENDP
  518.  
  519.  
  520. ;-------------------------------------------------
  521. ; entry: AL = INTERRUPT NUM                      |
  522. ;        DX = new vector ofs, seg is alway CS    |
  523. ;        BX = offset of store buffer             :
  524. ;-------------------------------------------------
  525. SETUP_INTERRUPT    PROC
  526.  
  527.        PUSHF
  528.        PUSH   BX
  529.        PUSH   CX
  530.        PUSH   DX
  531.  
  532.        CLI
  533.  
  534.        MOV    CL,AL                    ; preserve interrupt number for use
  535.  
  536.        ADD    AL,8                     ; calculate interrupt vector addx
  537.        CBW
  538.        SHL    AL,1
  539.        SHL    AL,1
  540.        MOV    DI,AX
  541.  
  542.        PUSH   ES                       ; setup and preserve interrupt
  543.        SUB    AX,AX
  544.        MOV    ES,AX
  545.        MOV    AX,ES:[DI]
  546.        MOV    [BX],AX
  547.        MOV    ES:[DI],DX
  548.  
  549.        MOV    AX,ES:[DI+2]
  550.        MOV    [BX+2],AX
  551.        MOV    ES:[DI+2],CS
  552.  
  553.        POP    ES
  554.  
  555.        POP    DX
  556.        POP    CX
  557.        POP    BX
  558.        POPF
  559.        RET
  560.  
  561. SETUP_INTERRUPT    ENDP
  562.  
  563.  
  564. ;-------------------------------------------------
  565. ; entry: AL = INTERRUPT NUM                      |
  566. ;        BX = offset to stored addx              |
  567. ;-------------------------------------------------
  568. RESTORE_INTERRUPT  PROC
  569.  
  570.        PUSHF
  571.  
  572.        CLI
  573.  
  574.        MOV    CL,AL
  575.  
  576.        ADD    AL,8                      ; calculate interrupt vector addx
  577.        CBW
  578.        SHL    AL,1
  579.        SHL    AL,1
  580.        MOV    DI,AX
  581.  
  582.        PUSH   ES                       ; restore interrupt vector
  583.        SUB    AX,AX
  584.        MOV    ES,AX
  585.        MOV    AX,[BX]
  586.        MOV    ES:[DI],AX
  587.  
  588.        MOV    AX,[BX+2]
  589.        MOV    ES:[DI+2],AX
  590.  
  591.        POP    ES
  592.  
  593.        MOV    AH,1
  594.        SHL    AH,CL
  595.  
  596.        IN     AL,21H
  597.        OR     AL,AH
  598.        OUT    21H,AL
  599.  
  600.        POPF
  601.        RET
  602.  
  603. RESTORE_INTERRUPT  ENDP
  604.  
  605.  
  606. DUMMY_DMA_INT2      PROC   FAR
  607.  
  608.        PUSH   DX
  609.        MOV    DL,2
  610.        JMP    SHORT DUMMY_DMA_ISR
  611.  
  612. DUMMY_DMA_INT2      ENDP
  613.  
  614.  
  615. DUMMY_DMA_INT3      PROC   FAR
  616.  
  617.        PUSH   DX
  618.        MOV    DL,3
  619.        JMP    SHORT DUMMY_DMA_ISR
  620.  
  621. DUMMY_DMA_INT3      ENDP
  622.  
  623.  
  624. DUMMY_DMA_INT5      PROC   FAR
  625.  
  626.        PUSH   DX
  627.        MOV    DL,5
  628.        JMP    SHORT DUMMY_DMA_ISR
  629.  
  630. DUMMY_DMA_INT5      ENDP
  631.  
  632.  
  633. DUMMY_DMA_INT7      PROC   FAR
  634.  
  635.        PUSH   DX
  636.        MOV    DL,7
  637.  
  638. DUMMY_DMA_ISR:
  639.  
  640.        PUSH   DS
  641.        PUSH   AX
  642.  
  643.        MOV    AX,DGROUP
  644.        MOV    DS,AX
  645.  
  646.        MOV    _intr_num,DL
  647.  
  648.        MOV    DX,_io_addx
  649.        ADD    DX,0EH
  650.        IN     AL,DX
  651.  
  652.        MOV    AL,20H
  653.        OUT    20H,AL
  654.  
  655.        POP    AX
  656.        POP    DS
  657.        POP    DX
  658.        IRET
  659.  
  660. DUMMY_DMA_INT7      ENDP
  661.  
  662.  
  663.  
  664. DMA_OUT_INTR    PROC
  665.  
  666.        PUSH   DS
  667.        PUSH   ES
  668.        PUSH   AX
  669.        PUSH   BX
  670.        PUSH   CX
  671.        PUSH   DX
  672.        PUSH   DI
  673.        PUSH   SI
  674.        PUSH   BP
  675.  
  676.        CLD
  677.        MOV    AX,DGROUP
  678.        MOV    DS,AX
  679.        MOV    ES,AX
  680.  
  681.        MOV    DX,_io_addx
  682.        ADD    DL,0EH
  683.        IN     AL,DX
  684.  
  685.        MOV    AX,LEN_L_TO_DMA
  686.        OR     AX,AX
  687.        JNZ    VO_INT10
  688.  
  689.        CALL   END_DMA_TRANSFER
  690.  
  691.        JMP    SHORT VO_INT90
  692.  
  693. VO_INT10:
  694.        CALL   DMA_OUT_TRANSFER
  695.  
  696. VO_INT90:
  697.        MOV    AL,20H
  698.        OUT    20H,AL
  699.  
  700.        POP    BP
  701.        POP    SI
  702.        POP    DI
  703.        POP    DX
  704.        POP    CX
  705.        POP    BX
  706.        POP    AX
  707.        POP    ES
  708.        POP    DS
  709.        IRET
  710.  
  711. DMA_OUT_INTR    ENDP
  712.  
  713.  
  714.  
  715. DMA_OUT_TRANSFER     PROC
  716.  
  717.        MOV    CX,0FFFFH                ; get current page end address
  718.  
  719.        CMP    PAGE_TO_DMA,0            ; last page to dma ?
  720.        JNZ    DOT10                    ; no, skip
  721.  
  722.        INC    PAGE_TO_DMA
  723.        MOV    CX,LAST_DMA_OFFSET       ; get end addx
  724.  
  725. DOT10:
  726.        SUB    CX,DMA_CURRENT_ADDX      ; calcutate current page addx
  727.        MOV    DMA_CURRENT_COUNT,CX
  728.        INC    CX
  729.        JZ     DOT20
  730.  
  731.        SUB    LEN_L_TO_DMA,CX
  732.        SBB    LEN_H_TO_DMA,0
  733.        JMP    SHORT DOT30
  734.  
  735. DOT20:                  
  736.        DEC    LEN_H_TO_DMA
  737.  
  738. DOT30:
  739.        MOV    DH,DMA_VOICE_OUT
  740.        MOV    DL,DMA_CURRENT_PAGE
  741.        MOV    AX,DMA_CURRENT_ADDX
  742.        MOV    CX,DMA_CURRENT_COUNT
  743.        CALL   PROG_DMA
  744.  
  745.        DEC    PAGE_TO_DMA
  746.        INC    DMA_CURRENT_PAGE
  747.        MOV    DMA_CURRENT_ADDX,0
  748.  
  749.        MOV    CX,DMA_CURRENT_COUNT
  750.  
  751.        MOV    DX,_io_addx
  752.        ADD    DL,0CH
  753.  
  754.        MOV    AL,DSP_VO8_CMD
  755.        CALL   WRITE_DSP
  756.  
  757.        MOV    AL,CL
  758.        CALL   WRITE_DSP
  759.  
  760.        MOV    AL,CH
  761.        CALL   WRITE_DSP
  762.  
  763. DOT90:
  764.        RET
  765.  
  766. DMA_OUT_TRANSFER     ENDP
  767.  
  768.  
  769.  
  770. END_DMA_TRANSFER     PROC
  771.  
  772.        MOV    AL,5
  773.        OUT    DMA_MASK_REG,AL
  774.  
  775.        MOV    CL,_intr_num
  776.        MOV    AH,1
  777.        SHL    AH,CL
  778.        IN     AL,21H
  779.        OR     AL,AH
  780.        OUT    21H,AL
  781.  
  782.        MOV    AL,_intr_num
  783.        MOV    BX,OFFSET DGROUP:ORG_INT_ADDX
  784.        CALL   RESTORE_INTERRUPT
  785.  
  786.        MOV    _voice_status,0
  787.  
  788.        MOV    DX,_io_addx
  789.        ADD    DL,0EH
  790.        IN     AL,DX
  791.  
  792.        RET
  793.  
  794. END_DMA_TRANSFER     ENDP
  795.  
  796.  
  797. ;---------------------------------------
  798. ;  WAIT_FM_STATUS                      :
  799. ;   entry:    AL = status to wait      :
  800. ;                  3 msb is concern    :
  801. ;   exit :    AX destroy               :
  802. ;             carry set for fail       :
  803. ;             carry clr for pass       :
  804. ;---------------------------------------
  805. WAIT_FM_STATUS     PROC
  806.  
  807.        PUSH   CX
  808.        PUSH   DX
  809.  
  810.        MOV    CX,FM_WAIT_TIME
  811.  
  812.        MOV    AH,AL
  813.        AND    AH,0E0H                  ; only 3 msb are FM status
  814.        MOV    DX,_io_addx
  815.        ADD    DL,8
  816.  
  817. WFS10:
  818.        IN     AL,DX
  819.        AND    AL,0E0H
  820.        CMP    AH,AL
  821.        JE     WFS20
  822.  
  823.        LOOP   WFS10
  824.  
  825.        STC
  826.        JMP    SHORT WFS90
  827.  
  828. WFS20:
  829.        CLC
  830.  
  831. WFS90:
  832.        POP    DX
  833.        POP    CX
  834.        RET
  835.  
  836. WAIT_FM_STATUS     ENDP
  837.  
  838.  
  839. ;---------------------------------------
  840. ;  WRITE_FM                            :
  841. ;   entry:    AH = data value          :
  842. ;             AL = addx value          :
  843. ;   exit :    AX destroy               :
  844. ;             DX destroy               :
  845. ;---------------------------------------
  846. WRITE_FM         PROC
  847.  
  848.        MOV    DX,_io_addx
  849.        ADD    DL,8
  850.        OUT    DX,AL
  851.        CALL   FM_DELAY
  852.        MOV    AL,AH
  853.        INC    DX
  854.        OUT    DX,AL
  855.        CALL   FM_DELAY
  856.        RET
  857.  
  858. WRITE_FM         ENDP
  859.  
  860.  
  861. FM_DELAY         PROC
  862.  
  863.        PUSH   AX
  864.        PUSH   DX
  865.  
  866.        MOV    DX,_io_addx
  867.        ADD    DL,8
  868.  
  869.        IN     AL,DX
  870.        IN     AL,DX
  871.        IN     AL,DX
  872.        IN     AL,DX
  873.        IN     AL,DX
  874.  
  875.        POP    DX
  876.        POP    AX
  877.  
  878.        RET
  879.  
  880. FM_DELAY         ENDP
  881.  
  882.  
  883.  
  884.  
  885.  
  886. ifdef  small
  887.     _ctv_detect      PROC
  888. else
  889.     _ctv_detect      PROC    FAR
  890. endif
  891.        PUSH   DS
  892.        PUSH   ES
  893.        PUSH   DI
  894.        PUSH   SI
  895.  
  896.        MOV    AX,DGROUP
  897.        MOV    DS,AX
  898.        MOV    ES,AX
  899.  
  900.        CALL   RESET_DSP
  901.        JNZ    ID90
  902.  
  903.        CALL   VERIFY_IO_CHK
  904.        JNZ    ID90
  905.  
  906.        CALL   CHK_DSP_VERSION
  907.        JNZ    ID90
  908.  
  909.        CALL   VERIFY_INTR
  910.        JNZ    ID90
  911.  
  912.        MOV    AL,1                     ; on speaker
  913.        CALL   ON_OFF_SPEAKER
  914.  
  915.        SUB    AX,AX
  916.  
  917. ID90:
  918.        POP    SI
  919.        POP    DI
  920.        POP    ES
  921.        POP    DS
  922.        RET
  923.  
  924. _ctv_detect      ENDP
  925.  
  926.  
  927. SPK_STK          STRUC
  928.  
  929. ifdef    small
  930.                    DW      ?
  931. else
  932.                    DD      ?
  933. endif
  934.  
  935.                    DW      ?
  936.     SPK_FLAG       DW      ?
  937.  
  938. SPK_STK          ENDS
  939.  
  940.  
  941. ifdef  small
  942.     _ctv_speaker     PROC
  943. else
  944.     _ctv_speaker     PROC    FAR
  945. endif
  946.  
  947.        PUSH   BP
  948.        MOV    BP,SP
  949.  
  950.        PUSH   DS
  951.  
  952.        MOV    AX,DGROUP
  953.        MOV    DS,AX
  954.  
  955.        MOV    AX,[BP+SPK_FLAG]
  956.        CALL   ON_OFF_SPEAKER
  957.  
  958.  
  959.        POP    DS
  960.  
  961.        POP    BP
  962.        RET
  963.  
  964. _ctv_speaker  ENDP
  965.  
  966.  
  967. ON_OFF_SPEAKER     PROC
  968.  
  969.  
  970.        MOV    DX,_io_addx
  971.        ADD    DX,0CH
  972.  
  973.        MOV    AH,DSP_ONSPK_CMD
  974.        OR     AL,AL
  975.        JNZ    OOS10
  976.  
  977.        MOV    AH,DSP_OFFSPK_CMD
  978.  
  979. OOS10:
  980.        MOV    AL,AH
  981.        CALL   WRITE_DSP
  982.  
  983.        SUB    AX,AX                    ; inidcate no error
  984.        RET
  985.  
  986. ON_OFF_SPEAKER     ENDP
  987.  
  988.  
  989.  
  990. OUT_STK       STRUC
  991.  
  992. ifdef  small
  993.            DW      ?                   ; one word ret addx
  994. else                                                      
  995.            DD      ?                   ; double word ret addx
  996. endif
  997.                    DW   ?
  998.     BUF_OFF        DW   ?
  999.     BUF_SEG        DW   ?
  1000.     COUNT          DW   ?
  1001.     SAMPLING       DW   ?
  1002.  
  1003. OUT_STK       ENDS
  1004.  
  1005.  
  1006. ifdef  small
  1007.     _ctv_output      PROC
  1008. else
  1009.     _ctv_output      PROC    FAR
  1010. endif
  1011.  
  1012.        PUSH   BP
  1013.        MOV    BP,SP
  1014.  
  1015.        PUSH   DS
  1016.        PUSH   ES
  1017.        PUSH   DI
  1018.        PUSH   SI
  1019.  
  1020.        MOV    AX,DGROUP
  1021.        MOV    DS,AX
  1022.        MOV    ES,AX
  1023.  
  1024.        CMP    _voice_status,0
  1025.        JZ     OV10
  1026.  
  1027.        MOV    AX,1
  1028.        JMP    OV90
  1029.  
  1030. OV10:
  1031.        MOV    _voice_status,1
  1032.  
  1033.        MOV    DX,_io_addx
  1034.        ADD    DL,0CH
  1035.  
  1036.        MOV    DX,0FH                   ; calculate sampling rate value for
  1037.        MOV    AX,4240H                 ; DSP
  1038.        MOV    CX,[BP+SAMPLING]
  1039.        DIV    CX
  1040.  
  1041.        MOV    CL,AL
  1042.        NEG    CL
  1043.  
  1044.        MOV    DX,_io_addx
  1045.        ADD    DL,0CH
  1046.        MOV    AL,DSP_TIME_CMD
  1047.        CALL   WRITE_DSP
  1048.  
  1049.        MOV    AL,CL
  1050.        CALL   WRITE_DSP
  1051.  
  1052.        MOV    AL,_intr_num
  1053.        MOV    DX,OFFSET DMA_OUT_INTR
  1054.        MOV    BX,OFFSET DGROUP:ORG_INT_ADDX
  1055.        CALL   SETUP_INTERRUPT
  1056.  
  1057.        MOV    CL,_intr_num
  1058.        MOV    AH,1
  1059.        SHL    AH,CL
  1060.        NOT    AH
  1061.        IN     AL,21H
  1062.        AND    AL,AH
  1063.        OUT    21H,AL
  1064.  
  1065.        MOV    DX,[BP+BUF_SEG]
  1066.        MOV    AX,[BP+BUF_OFF]
  1067.        CALL   CALC_20BIT_ADDX
  1068.  
  1069.        MOV    DMA_CURRENT_PAGE,DL
  1070.        MOV    DMA_CURRENT_ADDX,AX
  1071.  
  1072.        MOV    CX,[BP+COUNT]
  1073.        MOV    LEN_L_TO_DMA,CX
  1074.        MOV    LEN_H_TO_DMA,0
  1075.  
  1076.        ADD    AX,[BP+COUNT]
  1077.        ADC    DL,0
  1078.        SUB    AX,1
  1079.        SBB    DL,0
  1080.  
  1081.        MOV    LAST_DMA_OFFSET,AX
  1082.        SUB    DL,DMA_CURRENT_PAGE
  1083.        MOV    PAGE_TO_DMA,DL
  1084.  
  1085.        CALL   DMA_OUT_TRANSFER
  1086.  
  1087.        SUB    AX,AX
  1088.  
  1089. OV90:
  1090.        POP    SI
  1091.        POP    DI
  1092.        POP    ES
  1093.        POP    DS
  1094.  
  1095.        POP    BP
  1096.        RET
  1097.  
  1098. _ctv_output      ENDP
  1099.  
  1100.  
  1101. ifdef  small
  1102.     _ctv_halt     PROC
  1103. else
  1104.     _ctv_halt     PROC     FAR
  1105. endif
  1106.  
  1107.        PUSH   DS
  1108.        PUSH   ES
  1109.        PUSH   DI
  1110.        PUSH   SI
  1111.  
  1112.        MOV    AX,DGROUP
  1113.        MOV    DS,AX
  1114.        MOV    ES,AX
  1115.  
  1116.        MOV    AX,1
  1117.  
  1118.        CMP    _voice_status,0
  1119.        JZ     TVP90
  1120.  
  1121.        CALL   PAUSE_DSP_DMA
  1122.        CALL   END_DMA_TRANSFER
  1123.  
  1124.        SUB    AX,AX
  1125.  
  1126. TVP90:
  1127.        POP    SI
  1128.        POP    DI
  1129.        POP    ES
  1130.        POP    DS
  1131.        RET
  1132.  
  1133. _ctv_halt     ENDP
  1134.  
  1135.  
  1136. ifdef  small
  1137.     _ctv_pause    PROC
  1138. else
  1139.     _ctv_pause    PROC     FAR
  1140. endif
  1141.  
  1142.        PUSH   DS
  1143.        PUSH   ES
  1144.        PUSH   DI
  1145.        PUSH   SI
  1146.  
  1147.        MOV    AX,DGROUP
  1148.        MOV    DS,AX
  1149.        MOV    ES,AX
  1150.  
  1151.        MOV    AX,1
  1152.  
  1153.        CMP    _voice_status,1
  1154.        JNE    PV90
  1155.  
  1156.        CALL   PAUSE_DSP_DMA
  1157.        SUB    AX,AX
  1158.  
  1159. PV90:
  1160.        POP    SI
  1161.        POP    DI
  1162.        POP    ES
  1163.        POP    DS
  1164.        RET
  1165.  
  1166. _ctv_pause    ENDP
  1167.  
  1168.  
  1169.  
  1170. ifdef  small
  1171.     _ctv_continue PROC
  1172. else
  1173.     _ctv_continue PROC  FAR
  1174. endif
  1175.  
  1176.        PUSH   DS
  1177.        PUSH   ES
  1178.        PUSH   DI
  1179.        PUSH   SI
  1180.  
  1181.        MOV    AX,DGROUP
  1182.        MOV    DS,AX
  1183.        MOV    ES,AX
  1184.  
  1185.        MOV    AX,1
  1186.  
  1187.        CMP    _voice_status,1
  1188.        JNE    CV90
  1189.  
  1190.        MOV    DX,_io_addx
  1191.        ADD    DL,0CH
  1192.  
  1193.        MOV    AL,DSP_CONT_DMA_CMD
  1194.        CALL   WRITE_DSP
  1195.        SUB    AX,AX
  1196.  
  1197. CV90:
  1198.        POP    SI
  1199.        POP    DI
  1200.        POP    ES
  1201.        POP    DS
  1202.        RET
  1203.  
  1204. _ctv_continue ENDP
  1205.  
  1206.  
  1207. ifdef  small
  1208.     _ctv_uninstall     PROC
  1209. else
  1210.     _ctv_uninstall     PROC  FAR
  1211. endif
  1212.  
  1213.        PUSH   DS
  1214.        PUSH   ES
  1215.        PUSH   DI
  1216.        PUSH   SI
  1217.  
  1218.        MOV    AX,DGROUP
  1219.        MOV    DS,AX
  1220.        MOV    ES,AX
  1221.  
  1222.        CMP    _voice_status,0
  1223.        JZ     UI90
  1224.  
  1225.        CALL   PAUSE_DSP_DMA
  1226.        CALL   END_DMA_TRANSFER
  1227.  
  1228.  
  1229. UI90:
  1230.        SUB    AL,AL
  1231.        CALL   ON_OFF_SPEAKER
  1232.  
  1233.        SUB    AX,AX
  1234.  
  1235.        POP    SI
  1236.        POP    DI
  1237.        POP    ES
  1238.        POP    DS
  1239.        RET
  1240.  
  1241. _ctv_uninstall     ENDP
  1242.  
  1243.  
  1244.     ;-----------------------------------------------------------
  1245.     ; usage:                                                   :
  1246.     ;        unint ctv_card_here()                              :
  1247.     ; description:                                             :
  1248.     ;    detect the Game Blaster or Sound Blaster Card and     :
  1249.     ;    the configuration                                     :
  1250.     ; entry:                                                   :
  1251.     ;   the global i/o addx, ct_io_addx must set to a default  :
  1252.     ;   value, 2x0H, before call.                              :
  1253.     ; exit:                                                    :
  1254.     ;   High Byte = 0                                          :
  1255.     ;   Low Byte format -                                      :
  1256.     ;      0000 0001  :   C/MS music exists                    :
  1257.     ;      0000 0010  :   FM music exists                      :
  1258.     ;      0000 0100  :   CTV Voice exists                     :
  1259.     ;-----------------------------------------------------------
  1260.  
  1261.  
  1262. ifdef small
  1263.     _ctv_card_here    PROC     near
  1264. else
  1265.     _ctv_card_here    PROC     far
  1266. endif
  1267.  
  1268.  
  1269.        PUSH   DS                       ; for multi data model, set DS to
  1270.        MOV    AX,DGROUP                ;  DGROUP segment
  1271.        MOV    DS,AX
  1272.  
  1273.        SUB    BX,BX                    ; assume Creative Card doesn't exist, 
  1274.                                        ;   return 0
  1275.     ;-----------------------------
  1276.     ;    detect Game Blaster     :
  1277.     ;-----------------------------
  1278.  
  1279.        MOV    DX,_io_addx           ; get default i/o addx
  1280.        ADD    DL,6                     ; write the test code to
  1281.        MOV    AL,CMS_TEST_CODE         ;   output port 2x6H
  1282.        OUT    DX,AL                    ; ...
  1283.        SUB    AL,AL
  1284.        ADD    DL,4                     ; read the data back from
  1285.        OUT    DX,AL
  1286.        IN     AL,DX                    ;   input port 2xAH
  1287.        CMP    AL,CMS_TEST_CODE         ; the same data ?
  1288.        JNE    CARD10                   ; no, try Sound Blaster Card
  1289.  
  1290.        SUB    DL,4                     ; to ensure, try inverse data
  1291.        MOV    AL,NOT CMS_TEST_CODE     ; output port 2x6H
  1292.        OUT    DX,AL                    ; ...
  1293.        SUB    AL,AL
  1294.        ADD    DL,4                     ; read the data back from
  1295.        OUT    DX,AL
  1296.        IN     AL,DX                    ;   input port 2xAH
  1297.        CMP    AL,NOT CMS_TEST_CODE     ; the same data ?
  1298.        JNE    CARD10                   ; no, try Sound Blaster Card
  1299.  
  1300.        MOV    BX,CMS_EXIST
  1301.        JMP    SHORT CARD50
  1302.  
  1303.     ;--------------------------------------
  1304.     ;    detect the Sound Blaster Card    :
  1305.     ;--------------------------------------
  1306. CARD10:
  1307.        CALL   RESET_DSP
  1308.        JNZ    CARD50
  1309.  
  1310. CARD40:
  1311.        MOV    DX,_io_addx
  1312.        ADD    DL,0CH
  1313.  
  1314.        MOV    AL,DSP_ID_CMD
  1315.        CALL   WRITE_DSP_TIME
  1316.        JC     CARD50
  1317.  
  1318.        MOV    AL,CMS_TEST_CODE
  1319.        CALL   WRITE_DSP_TIME
  1320.        JC     CARD50
  1321.  
  1322.        CALL   READ_DSP_TIME
  1323.        JC     CARD50
  1324.  
  1325.        CMP    AL,NOT CMS_TEST_CODE
  1326.        JNE    CARD50
  1327.  
  1328.        MOV    BX,CMS_EXIST + CTV_VOICE_EXIST
  1329.  
  1330.  
  1331.     ;-----------------------------
  1332.     ;    detect the FM Music     :
  1333.     ;-----------------------------
  1334. CARD50:
  1335.        MOV    AX,0001H                 ; reset the FM chip
  1336.        CALL   WRITE_FM
  1337.  
  1338.        MOV    AX,6004H                 ; mask of timer 1 & 2
  1339.        CALL   WRITE_FM
  1340.  
  1341.        MOV    AX,8004H                 ; reset irq and both timer flags
  1342.        CALL   WRITE_FM
  1343.  
  1344.        MOV    AL,0                     ; read for 3 msb clear
  1345.        CALL   WAIT_FM_STATUS
  1346.        JC     CARD90
  1347.  
  1348.        MOV    AX,0FF02H                ; write timer 1 count
  1349.        CALL   WRITE_FM
  1350.  
  1351.        MOV    AX,2104H                 ; start timer 1
  1352.        CALL   WRITE_FM
  1353.  
  1354.        MOV    AL,0C0H                  ; wait for irq and timer 1 end
  1355.        CALL   WAIT_FM_STATUS
  1356.        JC     CARD90
  1357.  
  1358.        MOV    AX,6004H                 ; mask of timer 1 & 2
  1359.        CALL   WRITE_FM
  1360.  
  1361.        MOV    AX,8004H                 ; reset irq and both timer flags
  1362.        CALL   WRITE_FM
  1363.  
  1364.        ADD    BX,FM_MUSIC_EXIST
  1365.  
  1366. CARD90:
  1367.        MOV    AX,BX
  1368.  
  1369.        POP    DS
  1370.        RET
  1371.  
  1372. _ctv_card_here    ENDP
  1373.  
  1374. ifdef  small
  1375.  
  1376.     _TEXT  ENDS
  1377. else
  1378.     CTV_TEXT     ENDS
  1379. endif
  1380.        END
  1381.  
  1382.  
  1383.  
  1384. 
  1385.